import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import Stats from 'stats-js';

import * as Util from "./utils";


export class General {
    constructor(id) {
        this.id = id;
        this.autoSize();
        this.camera = null;
        this.scene = null;
        this.renderer = null;
        this.stats = null;
        
        this.clock = new THREE.Clock();
    }
    autoSize () {
        let MARGIN = 2;
        let sz = Util.getSize(this.id);
        this.SCREEN_HEIGHT = sz.height - MARGIN * 2;
        this.SCREEN_WIDTH = sz.width;
    }

    init () {
        this.scene = new THREE.Scene();
        this.create();
        this.initRender();
        this.created();
    }

    create () {
        this.camera = new THREE.PerspectiveCamera( 75, this.SCREEN_WIDTH / this.SCREEN_HEIGHT, 0.1, 1000 );
        this.camera.position.z = 5;

        this.addTest();
    }
    created () {

    }

    addTest () {
        var geometry = new THREE.BoxGeometry( 1, 1, 1 );
        var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
        var cube = new THREE.Mesh( geometry, material );
        this.scene.add( cube );

        let helper = new THREE.GridHelper( 1000, 50, 0xff0000, 0x00ffff );
        this.scene.add( helper );
        
        let ambientLight = new THREE.AmbientLight(0xffffff, 0.1); // 0.1
        this.scene.add(ambientLight);
    }

    initRender () {
        this.renderer = new THREE.WebGLRenderer( { antialias: true } );
        this.renderer.setPixelRatio( window.devicePixelRatio );
        this.renderer.setSize( this.SCREEN_WIDTH, this.SCREEN_HEIGHT );
        let parent = document.getElementById(this.id);
        parent.appendChild( this.renderer.domElement );

        if (this.camera) this.controls = new OrbitControls( this.camera, this.renderer.domElement );

        this.stats = new Stats();
        parent.appendChild( this.stats.dom );
    }

    // render
    update (delta) {
        
    }

    render (delta) {
        if (delta === undefined) delta = this.clock.getDelta();
        this.update(delta);
        
        this.renderer.render( this.scene, this.camera );
        if (this.stats) this.stats.update();
    }

    windowResize () {
        this.autoSize();
        this.camera.aspect = this.SCREEN_WIDTH / this.SCREEN_HEIGHT;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize( this.SCREEN_WIDTH, this.SCREEN_HEIGHT );
    }
}
// End Class General


export function createGeneral (id, e, autoAnimate = true) {
    e = e || new General(id);
    
    function Animate (callback) {
        animate();
        function animate() {
            requestAnimationFrame( animate );
            if (callback) callback(e.clock.getDelta());
            e.render();
        }
    }

    if (autoAnimate) {
        e.init();
        Animate();
    }

    window.addEventListener( 'resize', function () {
        e.windowResize();
    }, false );

    return Animate;
}